I know this topic is in the usenet C FAQ, but they just offer a one-sentence answer saying it's not strictly in adherence to the standard but not much else, so here goes:
I was given an API for some network-based stuff and the header was littered with things like: (this is overly simplified)
Code:
#pragma pack(push,1)
typedef struct {
unsigned long packetid;
unsigned char data[0];
} packet_t;
#pragma pack(pop)
Fortunately my compiler understood the pragma. It did NOT, however, like the empty array.
I had never seen anything like this before. And so like an idiot my first instict was to just change it to (unsigned char*), yeah bad idea... now I see why they did it that way. (Well maybe I do?)
No, actually I don't understand, now that I've just typed that. Assuming he's the just victim of memcpy() calls, there are a billion other ways to handle that without such things, yes? Worst case you've got a "&" in each call. Anyway that's a side issue and not my real question.
The problem stems from the fact that the actual implementation contains sizeof(packet_t) _everywhere_. And from reading the code it seems that the zero-length array must not take up any space.
So my question is quite simply what is the easiest way to fix this?
What I ended up doing was changing the struct member to data[1] and then unfortunately I had to go through and find every instance ot sizeof(packet_t) and replace it with sizeof(packet_t) - 1. Actually not a literal "-1", but rather a constant using many FOUR_LETTER_WORDS which gets eval'd as (-1). Everywhere in the darn code, and since it wasn't just one struct I had a lot of reading to do.
This worked. Or seemed to. With such a kludgy solution I can't help but wonder if I missed that one place, and the thing will crash/hang if exactly one fewer bytes comes in off the wire.
Is there a better way that doesn't depend on compiler-specific tricks?
Especially keeping in mind the company's next version of the API will likely contain the same kind of thing and I'll have to do it all again? Something oh I dunno like:
Code:
#pragma humor_me_guys sizeof(packet_t) = sizeof(packet_t)-1
(half-joking), or perhaps a creative use of a union which is portable? Anything.